package proxyDemo;

import com.sun.xml.internal.ws.api.model.wsdl.WSDLOutput;
import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;
import org.junit.Test;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.Properties;

public class ProxyTest {
    @Test
    public void note(){
        //动态代理为的是将目标类进行一些增强操作
    }
}

//本体和静态代理共同实现的接口
interface Speaker{
    public void speak();
}


//实现接口的原对象
class ZhangSan implements Speaker{

    @Override
    public void speak() {
        System.out.println("我是原对象");
    }
}


//不实现接口的原对象
class Lisi{
    public void speak(){
        System.out.println("我是不实现接口的被代理对象");
    }
}


//一个代理对应一个本体，其内部有一个本体的实例
//静态代理，对象和代理类绑定，当有多个不同的需要代理的类时这样做及其不灵活且开销极大
class Proxyer implements Speaker{

    //代理类中的原对象
    ZhangSan zhangSan = new ZhangSan();

    @Override
    public void speak() {
        System.out.println("代理对象的更多功能");
        zhangSan.speak();  //原对象的原有功能
    }
}

//jdk自带的动态代理方式，需要实现InvocationHandler接口，重写invoke方法
class JdkDynamicProxy implements InvocationHandler {

    //不指定具体对象
    private Object obj;

    public JdkDynamicProxy(Object obj){
        this.obj = obj;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        if(method.getName().equals("speak")) {
            System.out.println("Jdk动态代理对象的更多功能");
            method.invoke(obj, args);  //通过反射来实现原对象功能
        }
        return null;
    }
}

//CGlib的动态代理方式（CGLib动态代理，它是在内存中构建一个子类对象，从而实现对目标对象功能的扩展，是基于继承来实现代理，所以无法对final类、private方法和static方法进行代理）
class CGlibDynamicProxy implements MethodInterceptor{

    private Object obj;

    public CGlibDynamicProxy(Object obj) {
        this.obj = obj;
    }

    @Override
    public Object intercept(Object o, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
        if(method.getName().equals("speak")) {
            System.out.println("CGlib动态代理对象的更多功能");
            method.invoke(obj, args);  //通过反射来实现原对象功能
        }
        return null;
    }
}

class Demo{
    public static void main(String[] args) {
        //静态代理
        Speaker speaker = new Proxyer();
        speaker.speak();

        //jdk的动态代理（被代理对象必须实现接口才可，比如此中的Speaker接口，若非如此则无法实现jdk的动态代理）
        JdkDynamicProxy jdkDynamicProxy = new JdkDynamicProxy(new ZhangSan());  //这里就是动态代理的好处，可以传任意对象，李四王五
        Speaker speaker1 = (Speaker)Proxy.newProxyInstance(Demo.class.getClassLoader(),new Class[]{Speaker.class},jdkDynamicProxy);
        speaker1.speak();

        //CGlib的动态代理（被代理对象无需实现接口，是一个第三方的jar包）
        CGlibDynamicProxy cGlibDynamicProxy = new CGlibDynamicProxy(new Lisi());
        Lisi lisi = (Lisi)Enhancer.create(Lisi.class,cGlibDynamicProxy);
        lisi.speak();

        //new Properties().var   快速new对象的快捷键，Properties是用来读取文件对象的类
        Properties properties = new Properties();
    }
}